package com.gitee.feizns.quickstart.web.ex.impl;

import com.gitee.feizns.quickstart.domain.vo.Ret;
import com.gitee.feizns.quickstart.web.ex.ErrorCodeEnums;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;

import java.util.List;


/**
 * {@link org.springframework.web.bind.annotation.RequestBody}
 * 上validate失败后抛出的异常是 MethodArgumentNotValidException 异常。
 * 控制器的上的请求实体类标注了 @RequestBody
 * 之后还需要使用 @Valid 或者 @Validated（两者都可以）
 * @link <a href="https://juejin.cn/post/6844904003684302861">Spring 参数校验的异常处理</a>
 * @see MethodArgumentNotValidException
 * @author feizns
 * @since 2019/7/7
 */
@NoArgsConstructor
public class MethodArgumentNotValidExceptionHandler extends AbstractExceptionHandler<MethodArgumentNotValidException> {

    /**
     * 响应的Http状态
     */
    private HttpStatus httpStatus = HttpStatus.BAD_REQUEST;

    public MethodArgumentNotValidExceptionHandler(HttpStatus httpStatus) {
        this.httpStatus = httpStatus;
    }

    @Override
    public ResponseEntity<Ret<?>> handle(MethodArgumentNotValidException e) {
        return ResponseEntity.status(httpStatus)
                .body(Ret.error(HttpStatus.BAD_REQUEST.value(), getDefaultMessage(e.getBindingResult())));
    }

    private static String getDefaultMessage(BindingResult e) {
        FieldError error = e.getFieldError();
        if ( error != null )
            return String.format("参数:[%s]%s", error.getField(), error.getDefaultMessage());
        List<ObjectError> errors = e.getAllErrors();
        if ( !CollectionUtils.isEmpty(errors) )
            return String.format("参数:[%s]%s", errors.get(0).getObjectName(), errors.get(0).getDefaultMessage());
        return ErrorCodeEnums.UNKNOWN.getMsg();
    }

}
